import { ExpressionEditorComponent, ExpressionEditorParam } from '@farris/designer-devkit';
import { IDesignerHost } from '@farris/designer-element';
import {
  DesignerEnvType,
  FormBindingType,
  FormExpression,
  StateMachineService,
  UniformEditorDataUtil
} from '@farris/designer-services';
import { ElementPropertyConfig } from '@farris/ide-property-panel';
import { FormPropertyChangeObject } from '../../../../entity/property-change-entity';
import { NoCodeInputProps } from '../../common/property/nocode-input-property-config';
export class ImageUploadProp extends NoCodeInputProps {

  stateMachineService: StateMachineService;
  propertyConfig: ElementPropertyConfig[];

  constructor(private serviceHost1: IDesignerHost, viewModelId: string, componentId: string) {
    super(serviceHost1, viewModelId, componentId);
    this.stateMachineService = serviceHost1.getService('StateMachineService');
  }
  getPropConfig(propertyData: any): ElementPropertyConfig[] {

    this.propertyConfig = [];

    // 基本信息属性
    const basicPropConfig = this.getBasicPropConfig(propertyData, this.viewModelId);
    this.propertyConfig.push(basicPropConfig);

    // 外观属性
    const appearanceProperties = this.getAppearancePropConfig(propertyData, this.viewModelId);
    this.propertyConfig.push(appearanceProperties);

    // 行为属性
    const behaviorPropConfig = this.getBehaviorPropConfig(propertyData, this.viewModelId);
    this.propertyConfig.push(behaviorPropConfig);

    // 服务器属性
    const customPropConfig = this.getServerPropConfig(propertyData, this.viewModelId);
    this.propertyConfig.push(customPropConfig);

    // 事件属性
    const eventPropConfig = this.getImageEventPropConfig(propertyData, this.viewModelId);
    this.propertyConfig.push(eventPropConfig);

    return this.propertyConfig;
  }


  private getBehaviorPropConfig(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig {
    let behaviorProperties = [];
    if (showPosition === 'card' || showPosition === 'tableTdEditor') {
      behaviorProperties = this.getPrivateBehaviorPropConfig(propertyData, viewModelId);
    }
    behaviorProperties.push(
      {
        propertyID: 'maxUploads',
        propertyName: '最大上传个数',
        propertyType: 'number',
        decimals: 0,
        min: 0,
        description: '值为0时表示不限制上传个数',
      },
      {
        propertyID: 'maxSize',
        propertyName: '允许图片大小（M）',
        propertyType: 'number',
        decimals: 0,
        min: 0,
        description: '图片最大size 单位M',
      },
      {
        propertyID: 'imgType',
        propertyName: '允许图片格式',
        propertyType: 'multiSelect',
        description: '图片限制的类型',
        iterator: [
          { key: 'png', value: 'png' },
          { key: 'jpg', value: 'jpg' },
          { key: 'jpeg', value: 'jpeg' },
          { key: 'webp', value: 'webp' },
          { key: 'svg', value: 'svg' },
          { key: 'gif', value: 'gif' },
          { key: 'bmp', value: 'bmp' }
        ],
        multiSelectDataType: 'array'
      },
      {
        propertyID: 'storeType',
        propertyName: '图片存储格式',
        propertyType: 'select',
        description: '选择图片存储的方式',
        iterator: [{ key: 'metadata', value: 'metadata' }, { key: 'base64', value: 'base64' }],
        defaultValue: 'metadata',
        visible: false // 仅有少量使用 base64 方式，后续不再支持
      }
    );
    const self = this;
    const config = {
      categoryId: 'behavior',
      categoryName: '行为',
      properties: behaviorProperties,
      setPropertyRelates(changeObject: FormPropertyChangeObject, prop, parameters) {
        self.changeBehaviorPropertyRelates(this.properties, changeObject, propertyData, parameters, showPosition);
      }
    };

    if (showPosition !== 'card') {
      Object.assign(config, {
        categoryId: showPosition + '_' + config.categoryId,
        propertyData,
        enableCascade: true,
        parentPropertyID: 'editor',
        tabId: showPosition,
        tabName: '编辑器'
      });
    }
    return config;
  }


  private getServerPropConfig(propertyData: any, viewModelId: string): ElementPropertyConfig {
    return {
      categoryId: 'server',
      categoryName: '服务器配置',
      properties: [
        {
          propertyID: 'rootId',
          propertyName: '图片服务器根目录',
          propertyType: 'string'
        },
        {
          propertyID: 'formId',
          propertyName: '二级目录',
          propertyType: 'unity',
          editorParams: {
            controlName: UniformEditorDataUtil.getControlName(propertyData),
            editorOptions: {
              types: ['custom', 'variable'],
              variables: UniformEditorDataUtil.getVariables(viewModelId, this.domService),
              getVariables: () => UniformEditorDataUtil.getVariables(viewModelId, this.domService),
              newVariableType: 'String'
            }
          },
          description: '必填，根据【附件信息】业务字段所在位置区分：1、在子表，二级目录建议绑定主表ID。2：在主表：二级目录建议填写当前表单元数据ID'
        }
      ]
    };
  }

  private getImageEventPropConfig(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig {
    const eventList = [
      {
        label: 'click',
        name: '点击事件'
      }
    ];
    return this.getEventPropertyConfig(propertyData, viewModelId, showPosition, { customEventList: eventList });

  }

  /**
   * table单元格编辑器属性
   * @param tdData 单元格数据
   * @param viewModelId viewModelId
   * @returns 属性配置
   */
  getTableTdEdtiorPropConfig(tdData: any, viewModelId: string): ElementPropertyConfig[] {
    const propertyData = tdData.editor;

    this.propertyConfig = [];


    // 行为属性
    const behaviorConfig = this.getBehaviorPropConfig(propertyData, viewModelId, 'tableTdEditor');
    behaviorConfig.properties = behaviorConfig.properties.filter(p => !'binding,visible'.includes(p.propertyID));
    this.propertyConfig.push(behaviorConfig);


    // 表达式属性
    const exprPropConfig = this.getExpressionPropConfig(propertyData, viewModelId, 'tableTdEditor');
    if (exprPropConfig) {
      this.propertyConfig.push(exprPropConfig);
    }

    // 事件属性
    const eventConfig = this.getImageEventPropConfig(propertyData, viewModelId, 'tableTdEditor');
    this.propertyConfig.push(eventConfig);

    return this.propertyConfig;
  }

  getPrivateBehaviorPropConfig(propertyData: any, viewModelId: string) {
    const bindingFieldId = propertyData.binding && propertyData.binding.type === FormBindingType.Form && propertyData.binding.field;
    const expField = this.domService.expressions && this.domService.expressions.find(e => e.fieldId === bindingFieldId);
    // 运行时定制环境中不允许新增变量，因为新增的变量没有入口配置变量值
    const canAddVariable = this.formBasicService.envType === DesignerEnvType.designer;
    // 为了发版，暂时将申报模板子表中的只读、必填属性的表达式选项屏蔽掉
    let showExpInTableTemplate = true;
    const vmBindTo = this.domService.getViewModelById(viewModelId).bindTo;
    if (this.domService.module.templateId === 'nav-table-fillin-form-template' && vmBindTo !== '/') {
      showExpInTableTemplate = false;
    }
    return [
      {
        propertyID: 'visible',
        propertyName: '是否可见',
        propertyType: 'unity',
        description: '运行时组件是否可见',
        editorParams: {
          constType: 'enum',
          editorOptions: {
            types: ['const', 'expression'],
            enums: [{ key: true, value: '是' }, { key: false, value: '否' }],
            expressionConfig:
            {
              editor: ExpressionEditorComponent,
              beforeOpenModal: () => this.getPrivateExpressionEditorParams(propertyData, '可见编辑器', 'visible'),
              exprValue: this.getPrivateExprValue(expField, propertyData.visible)
            }
          }
        }
      },
      {
        propertyID: 'readonly',
        propertyName: '只读',
        propertyType: 'unity',
        description: '是否只读',
        editorParams: {
          controlName: canAddVariable ? UniformEditorDataUtil.getControlName(propertyData) : undefined,
          constType: 'enum',
          editorOptions: {
            types: bindingFieldId && showExpInTableTemplate ? ['const', 'variable', 'custom', 'expression', 'stateMachine'] : ['const', 'variable', 'custom', 'stateMachine'],
            enums: [{ key: true, value: '是' }, { key: false, value: '否' }],
            variables: UniformEditorDataUtil.getVariables(viewModelId, this.domService),
            getVariables: () => UniformEditorDataUtil.getVariables(viewModelId, this.domService),
            newVariableType: 'Boolean',
            newVariablePrefix: 'is',
            expressionConfig:
            {
              editor: ExpressionEditorComponent,
              beforeOpenModal: () => this.getPrivateExpressionEditorParams(propertyData, '只读编辑器', 'readonly'),
              exprValue: this.getPrivateExprValue(expField, propertyData.readonly)
            },
            stateMachine: this.stateMachineService.stateMachineMetaData,
          }
        },
      },
      {
        propertyID: 'require',
        propertyName: '必填',
        propertyType: 'unity',
        description: '是否必填',
        editorParams: {
          constType: 'enum',
          editorOptions: {
            types: ['const', 'expression'],
            enums: [{ key: true, value: '是' }, { key: false, value: '否' }],
            expressionConfig:
            {
              editor: ExpressionEditorComponent,
              beforeOpenModal: () => this.getPrivateExpressionEditorParams(propertyData, '必填编辑器', 'require'),
              exprValue: this.getPrivateExprValue(expField, propertyData.require)
            }
          }
        }
      }
    ];
  }

  /**
   * 获取表达式编辑需要的参数：在属性面板弹出表达式窗口时调用
   */
  getPrivateExpressionEditorParams(propertyData: any, modalTitle: string, expressionType: string) {
    let expressionStr = null;
    const bindingFieldId = propertyData.binding && propertyData.binding.field;
    const expressionParams: ExpressionEditorParam = {
      modalTitle: modalTitle || '表达式编辑器',
      fieldId: bindingFieldId,
      viewModelId: this.viewModelId,
      expType: expressionType
    };

    // 必填表达式需要配置提示消息
    if (expressionType === 'require') {
      expressionParams.message = '';
    }


    const propertyValue = propertyData[expressionType];
    if (propertyValue && propertyValue.expressionId && bindingFieldId) {
      const expField = this.domService.expressions.find(e => e.fieldId === bindingFieldId);

      // 检测到现有的表达式配置
      if (expField) {
        const originalExpConfig = expField.expression.find(exp => exp.id === propertyValue.expressionId);
        expressionStr = originalExpConfig.value;

        if (expressionType === 'require') {
          expressionParams.message = originalExpConfig.message;
        }
      }
    }

    return {
      editorParams: expressionParams,
      value: expressionStr
    };
  }

  /**
   * 获取属性编辑器需要的初始绑定值
   * @param expField 表达式配置字段
   * @param propertyValue 属性值
   */
  getPrivateExprValue(expField: FormExpression, propertyValue: any) {
    let expressionStr = null;
    if (propertyValue && propertyValue.expressionId && expField) {
      const originalExpConfig = expField.expression.find(exp => exp.id === propertyValue.expressionId);
      expressionStr = originalExpConfig && originalExpConfig.value;

    }

    return {
      type: 'expression',
      value: {
        value: expressionStr,
        parameters: propertyValue && propertyValue.expressionId,
        type: 'Expression'
      }
    };
  }

}
